tArgs = {...}

OneOS.LoadAPI('/System/API/Drawing.lua')
OneOS.LoadAPI('/System/API/Button.lua')
OneOS.LoadAPI('/System/API/Helpers.lua')

Current = {
	Clicks = {},
}

Events = {
	
}

InterfaceElements = {
	
}

function Initialise()
	EventRegister('mouse_click', TryClick)
	EventRegister('mouse_drag', TryClick)
	EventRegister('monitor_touch', TryClick)
	EventRegister('mouse_scroll', Scroll)
	EventRegister('key', HandleKey)
	EventRegister('char', HandleKey)
	EventRegister('timer', Update)

	if fs.getFreeSpace and fs.getSize then
		systemSize = FolderSize('/System/') + OneOS.FS.getSize('startup')
		desktopSize = FolderSize('/Desktop/')
		programsSize = FolderSize('/Programs/')
		totalSize = FolderSize('/')
		maxSpace = OneOS.FS.getFreeSpace('/') + totalSize
	else
		maxSpace = -1
	end

	logo = Drawing.LoadImage('/System/Images/Logo')
	thanksLines = Helpers.WrapText('Thanks to GravityScore (LuaIDE), NitrogenFingers(GoldRunner, image stuff), Symmetryc & superaxander (GitHub issues), Jesusthekiller (Maze3D), Symmetryc (YCCCUP), Vilsol (help with App Store) and testers!', Drawing.Screen.Width-2)
	Update()
	EventHandler()
end

function Update()
	Draw()
	updateTimer = os.startTimer(1)
end

function Draw()
	Current.Clicks = {}
	Drawing.Clear(colours.white)

	for i, elem in ipairs(InterfaceElements) do
		if elem.Draw then
			elem:Draw()
		end
	end


	Drawing.DrawCharacters(10, 2, 'OneOS '..OneOS.Version, colours.grey, colours.white)
	Drawing.DrawCharacters(10, 3, '(c) oeed 2013 - 2014', colours.lightGrey, colours.white)
	Drawing.DrawCharacters(10, 4, 'Under CC BY-NC-ND 4.0 License', colours.lightGrey, colours.white)
	Drawing.DrawCharacters(10, 5, 'Click here for more license details', colours.lightGrey, colours.white)

	for i, line in ipairs(thanksLines) do
		Drawing.DrawCharacters(2, 6+i, line, colours.grey, colours.white)
	end
	

	Drawing.DrawImage(2, 2, logo, 6, 4)
	if maxSpace ~= -1 then
		local spacebarX = 2
		local spacebarY = Drawing.Screen.Height-3
		Drawing.DrawBlankArea(1, spacebarY-3, Drawing.Screen.Width, 7, colours.white)
		local spacebarWidth = Drawing.Screen.Width-2
		Drawing.DrawCharacters(spacebarX, spacebarY - 2, 'Storage Usage', colours.grey, colours.white)
		Drawing.DrawCharacters(spacebarX+15, spacebarY - 2, FormatBytes(totalSize)..' Used, '..FormatBytes(maxSpace - totalSize)..' Available', colours.lightGrey, colours.white)
		Drawing.DrawBlankArea(spacebarX, spacebarY, spacebarWidth, 1, colours.lightGrey)
		local otherWidth = math.ceil((totalSize/maxSpace)*spacebarWidth)
		Drawing.DrawBlankArea(spacebarX, spacebarY, otherWidth, 1, colours.yellow)

		local systemWidth = math.ceil((systemSize/maxSpace)*spacebarWidth)
		Drawing.DrawBlankArea(spacebarX, spacebarY, systemWidth, 1, colours.red)
		spacebarX = spacebarX + systemWidth
		local programsWidth = math.ceil((programsSize/maxSpace)*spacebarWidth)
		Drawing.DrawBlankArea(spacebarX, spacebarY, programsWidth, 1, colours.blue)
		spacebarX = spacebarX + programsWidth
		local desktopWidth = math.ceil((desktopSize/maxSpace)*spacebarWidth)
		Drawing.DrawBlankArea(spacebarX, spacebarY, desktopWidth, 1, colours.green)

		Drawing.WriteStringToBuffer(2, spacebarY+2, ' ', colours.black, colours.red)
		Drawing.DrawCharacters(4, spacebarY + 2, 'System', colours.grey, colours.white)
		Drawing.WriteStringToBuffer(12, spacebarY+2, ' ', colours.black, colours.blue)
		Drawing.DrawCharacters(14, spacebarY + 2, 'Programs', colours.grey, colours.white)
		Drawing.WriteStringToBuffer(24, spacebarY+2, ' ', colours.black, colours.green)
		Drawing.DrawCharacters(26, spacebarY + 2, 'Desktop', colours.grey, colours.white)
		Drawing.WriteStringToBuffer(35, spacebarY+2, ' ', colours.black, colours.yellow)
		Drawing.DrawCharacters(37, spacebarY + 2, 'Other', colours.grey, colours.white)
		Drawing.WriteStringToBuffer(44, spacebarY+2, ' ', colours.black, colours.lightGrey)
		Drawing.DrawCharacters(46, spacebarY + 2, 'Free', colours.grey, colours.white)
	end
	Drawing.DrawBuffer()
end

function FormatBytes(bytes)
	if bytes < 1024 then
		return "< 1KB"
	elseif bytes < 1024 * 1024 then
		return math.ceil(bytes / 1024) .. 'KB'
	elseif bytes < 1024 * 1024 * 1024 then
		--string.format('%.2f', ...) wasn't working for some reason
		local b = math.ceil((bytes / 1024 / 1024)*100)
		return b/100 .. 'MB'
	else
		return '> 1GB'
	end
end

function FolderSize(path)
	if path == '//.git' then
		return 0
	end
	local totalSize = 0
	for i, v in ipairs(OneOS.FS.list(path)) do
		if OneOS.FS.isDir(path..'/'..v) and path..'/'..v ~= '//rom' then
			totalSize = totalSize + FolderSize(path..'/'..v)
		else
			totalSize = totalSize + OneOS.FS.getSize(path..'/'..v)
		end
	end
	return totalSize
end

MainDraw = Draw

function RegisterElement(elem)
	table.insert(InterfaceElements, elem)
end

function UnregisterElement(elem)
	for i, e in ipairs(InterfaceElements) do
		if elem == e then
			InterfaceElements[i] = nil
		end
	end
end

function RegisterClick(elem)
	table.insert(Current.Clicks, elem)
end

function CheckClick(object, x, y)
	local pos = GetAbsolutePosition(object)
	if pos.X <= x and pos.Y <= y and  pos.X + object.Width > x and pos.Y + object.Height > y then
		return true
	end
end

function DoClick(event, object, side, x, y)
	if object and CheckClick(object, x, y) then
		return object:Click(side, x - object.X + 1, y - object.Y + 1)
	end	
end

function TryClick(event, side, x, y)
	if y == 5 and x >= 10 and x <= 44 then
		OneOS.OpenFile('/License')
		return
	end

	for i, object in ipairs(Current.Clicks) do
		if DoClick(event, object, side, x, y) then
			Draw()
			return
		end		
	end
end

function HandleKey(...)
	local args = {...}
	local event = args[1]
	local keychar = args[2]

	if keychar == keys.up then
		Scroll('mouse_scroll', -1)
	elseif keychar == keys.down then
		Scroll('mouse_scroll', 1)
	end
end

function GetAbsolutePosition(obj)
	if not obj.Parent then
		return {X = obj.X, Y = obj.Y}
	else
		local pos = GetAbsolutePosition(obj.Parent)
		local x = pos.X + obj.X - 1
		local y = pos.Y + obj.Y - 1
		return {X = x, Y = y}
	end
end

function EventRegister(event, func)
	if not Events[event] then
		Events[event] = {}
	end

	table.insert(Events[event], func)
end

function EventHandler()
	while true do
		local event = { coroutine.yield() }
		if Events[event[1]] then
			for i, e in ipairs(Events[event[1]]) do
				e(event[1], event[2], event[3], event[4], event[5])
			end
		end
	end
end

Initialise()